package rmmk.algorithms.features.global;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import rmmk.algorithms.preprocessing.filters.RemoveMostCommonFilter;
import rmmk.framework.datasources.Document;

/**
 * Klasa zliczająca globalnie ilość wystąpień danego słowa dla wszystkich
 * dokumentów
 * 
 * @author marcin
 * 
 */
public class GlobalWordCounts {

	private static Logger logger = LoggerFactory
			.getLogger(GlobalWordCounts.class);

	private static HashMap<String, Integer> results = new HashMap<>();

	public static void process(List<Document> documents) {

		// int cores = Runtime.getRuntime().availableProcessors();

		// temp = Collections.synchronizedMap(results);

		logger.info("Global words count started");
		for (Document doc : documents)
			for (String word : doc.getExtractedWords()) {
				if (results.containsKey(word)) {
					int i = results.get(word);
					results.put(word, ++i);
				} else
					results.put(word, 1);
			}

		logger.info("Global words count ended with " + results.size()
				+ " words");
	}

	public static HashMap<String, Integer> getWordCount() {
		return results;
	}

	private static String[] mostCommonCache = null;

	public static String[] getGlobalWords() {
		if (mostCommonCache != null)
			return mostCommonCache;

		logger.info("Generating global most common words cache");
		TreeMap<String, Integer> order = getOrder2((HashMap<String, Integer>) results);
		//TreeMap <Integer, String> order = getOrder2((HashMap<String, Integer>) results.clone());

		List<String> mostCommon = new ArrayList<>();

		int howMany = results.size() - (results.size() / 2000);
		int i = 0;

		for (Entry<String, Integer> result : order.entrySet())
			if (!(i++ < howMany))
				mostCommon.add(result.getKey());
		
		for(String s : RemoveMostCommonFilter.common)
			mostCommon.add(s);

		logger.info("Global most common words cache generated with " + mostCommon.size() + " instances");
		return mostCommonCache = mostCommon.toArray(new String[mostCommon.size()]);
	}

	static TreeMap<Integer, String> getOrder(
			HashMap<String, Integer> results2) {
		TreeMap<Integer, String> order = new TreeMap<>();
		int i = 0;
		
		
		
		while(!results2.isEmpty()){
			Iterator<Entry<String, Integer>> iterator = results2.entrySet().iterator();
			
			Entry<String, Integer> smallestEntry = iterator.next();
			
			while(iterator.hasNext())
			{
				Entry<String, Integer> current = iterator.next();
				
				if(current.getValue() < smallestEntry.getValue())
					smallestEntry = current;
			}
			
			order.put(i++, smallestEntry.getKey());
			results2.remove(smallestEntry.getKey());
			if(i%1000 == 0)
				logger.info("Pozostało: " + results2.size());
		}
		
		return order;
	}
	
	private static TreeMap<String, Integer> getOrder2(
			HashMap<String, Integer> results2) {
		GlobalWordCounts gwc = new GlobalWordCounts();
		ValueComparator bvc = gwc.new ValueComparator(results2);
		TreeMap<String, Integer> order = new TreeMap<String, Integer>(bvc);
		order.putAll(results2);
		
		return order;
	
	}
	
	private class ValueComparator implements Comparator<String> {

	    Map<String, Integer> base;
	    public ValueComparator(HashMap<String, Integer> results2) {
	        this.base = results2;
	    }

	    // Note: this comparator imposes orderings that are inconsistent with equals.    
	    public int compare(String a, String b) {
	        if (base.get(a) >= base.get(b)) {
	            return -1;
	        } else {
	            return 1;
	        } // returning 0 would merge keys
	    }
	}
}
